如果不透過框架,要如何寫出一個 GET 請求呢?在 JavaScript 中可以使用 XMLHttpRequest
的方法,但其實我平常也不太會這樣寫,主要原因也是難以閱讀及撰寫,我們大多都會使用框架來處理這段,如 jQuery, Axios...,以下略為介紹如何製作一個原生的 GET 請求:
本篇使用的是 https://randomuser.me/
隨機用戶產生器,這很適合用來作為 AJAX Get 的範例。
function reqOnload () {
const data = JSON.parse(this.responseText);
console.log(data)
}
function reqError (err) {
console.log('錯誤', err)
}
// 宣告一個 XHR 的物件
var Req = new XMLHttpRequest();
// 定義連線方式
Req.open('get', 'https://randomuser.me/api/', true);
// 送出請求
Req.send();
// 如果成功就執行 reqOnload()
Req.onload = reqOnload;
// 失敗就 reqError()
Req.onerror = reqError;
當然,在框架的時代我們已經習慣透過框架包裝以上的行為,讓程式碼的更為容易使用及閱讀,以 randomuser
網站所提供的範例來說,以上的行為可以寫成以下 (錯誤方法可參考 jQuery 文件),不需要在另外自己包裝發送的物件。
$.ajax({
url: 'https://randomuser.me/api/',
dataType: 'json',
success: function(data) {
console.log(data);
// 取得的遠端資料
}
});
XMLHttpRequest
在製作時每次都要新建一個請求的實體,而 AJAX 的網站,通常也不會只做一次請求而已,為了讓程式碼更容易維護及開發,大多開發者都會使用框架來包裝這類行為。
Fetch 在使用時看似與 jQuery $.ajax
挺相近的,所以在使用上也相對容易上手,不過兩者亦有不同概念之處(可參考)。
這裡提供一個簡單的範例來取得遠端的資料,這裡與 $.ajax 不同點在於:
ReadableStream
物件,需要使用不同資料類型使用對應方法,才能正確取得資料物件。fetch('https://randomuser.me/api/', {})
.then((response) => {
// 這裡會得到一個 ReadableStream 的物件
console.log(response);
// 可以透過 blob(), json(), text() 轉成可用的資訊
return response.json();
}).then((jsonData) => {
console.log(jsonData);
}).catch((err) => {
console.log('錯誤:', err);
});
fetch
後方會接 then()
,這是 Promise 的特性,資料取得後可在 then 裡面接收。return response.json();
的資料則會傳到下一個 then()
,至於詳細的 Promise 方法我們會留下一個章節介紹。
這裡如果刻意將網址打錯,會出現以下錯誤訊息。
fetch('https://randomuserkkk.me/api/', {})
Fetch API 的 Response 物件中的 body 屬性提供了一個 ReadableStream 的實體,這個階段我們無法直接讀取資料內容,而 ReadableStream 物件中可用以下對應的方法來取得資料 (https://developer.mozilla.org/zh-TW/docs/Web/API/Body):
像是以上的範例,我們可以將 response.json()
改為 response.text()
,那麼取得的資料格式將會是純字串。
也可以將資料轉為 blob
物件,像是圖片就可以做這樣的轉換 (這裡的圖片並非指圖片路徑,而是圖片檔案本身)。
// unsplash 上的圖片
let url = 'https://images.unsplash.com/photo-1513313778780-9ae4807465f0?auto=format&fit=crop&w=634&q=80'
fetch(url)
.then((response) => {
return response.blob();
})
.then((imageBlob) => {
let img = document.createElement('IMG')
document.querySelector('.newImg').appendChild(img);
// 將 blog 物件轉為 url
img.src = URL.createObjectURL(imageBlob);
})
URL 也是新的 API,可以將 blob 物件轉為網址
可在此網址看到完整範例:https://wcc723.github.io/javascript/2017/12/28/javascript-fetch/
六角的課程中有提供一個 POST
方法的練習(因為想不到哪裡可以測試 POST),下方的程式碼就可以對測試的機器發送 POST
,然後接受不同的結果 (這段 POST
並不會真的儲存帳密,只會將資料存在伺服器的記憶體,不久後會自動釋放)。
使用 fetch()
做 POST
時,由於它並沒有向一些框架一樣包那麼徹底,所以有些地方還是需要做調整,其中 body
所送出的資料必須先轉純字串後才能送出,以下範例就是一個簡單的 POST
行為。
let url = 'https://hexschool-tutorial.herokuapp.com/api/signup';
fetch(url, {
method: 'POST',
// headers 加入 json 格式
headers: {
'Content-Type': 'application/json'
},
// body 將 json 轉字串送出
body: JSON.stringify({
email: 'lovef1232e@hexschool.com',
password: '12345678'
})
}).then((response) => {
return response.json();
}).then((jsonData) => {
console.log(jsonData);
}).catch((err) => {
console.log('錯誤:', err);
})
所以這是第 25 篇了 (表示庫存已用完)。